home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / Other Langs / MacPerl ƒ / Perl Source ƒ / MacPerl / MPSave.c < prev    next >
Text File  |  1994-01-15  |  9KB  |  420 lines

  1. /*********************************************************************
  2. Project    :    MacPerl            -    Real Perl Application
  3. File        :    MPSave.c            -    Handle all the runtimes
  4. Author    :    Matthias Neeracher
  5.  
  6. A lot of this code is borrowed from 7Edit written by
  7. Apple Developer Support UK
  8.  
  9. Started    :    03Oct93                                Language    :    MPW C
  10. Modified    :    03Oct93    MN    Compiles correctly
  11. Last        :    03Oct93
  12. *********************************************************************/
  13.  
  14. #include <Errors.h>
  15. #include <Resources.h>
  16. #include <PLStringFuncs.h>
  17. #include <SysEqu.h>
  18. #include <Folders.h>
  19.  
  20. #include "MPSave.h"
  21. #include "MPGlobals.h"
  22. #include "MPFile.h"
  23. #include "MPUtils.h"
  24.  
  25. #pragma segment File
  26.  
  27. OSErr DoOpenResFile(FSSpec * spec, short * resFile, Boolean bundle)
  28. {
  29.     OSErr    err;
  30.     
  31.     *resFile = HOpenResFile(spec->vRefNum, spec->parID, spec->name, fsRdWrPerm);
  32.     if (*resFile == -1) {
  33.         if (err = DoCreate(*spec))
  34.             return err;
  35.  
  36.         *resFile =  HOpenResFile(spec->vRefNum, spec->parID, spec->name, fsRdWrPerm);
  37.         if (*resFile == -1) {
  38.             FileError("\perror opening file ", spec->name);
  39.             
  40.             return ResError();
  41.         }
  42.     }
  43.     
  44.     if (bundle) {
  45.         FInfo info;
  46.         
  47.         HGetFInfo(spec->vRefNum, spec->parID, spec->name, &info);
  48.         info.fdType        =    'APPL';
  49.         info.fdCreator    =    MPRtSig;
  50.         info.fdFlags     |= fHasBundle;
  51.         HSetFInfo(spec->vRefNum, spec->parID, spec->name, &info);
  52.     }
  53.     
  54.     return noErr;
  55. }
  56.  
  57. typedef struct {
  58.     OSType    type;
  59.     short        id;
  60.     OSType    realType;
  61. } ShoppingList;
  62.  
  63. OSErr    CopyShoppingList(short from, short to, ShoppingList * list)
  64. {
  65.     OSErr    err;
  66.     
  67.     while (list->type) {
  68.         Handle    rsrc;
  69.         Handle    nur;
  70.         
  71.         UseResFile(from);
  72.         
  73.         rsrc = Get1Resource(list->type, list->id);
  74.         
  75.         if (!rsrc)
  76.             return ResError();
  77.         
  78.         UseResFile(to);
  79.         
  80.         if (nur = Get1Resource(list->realType, list->id))
  81.             RmveResource(nur);
  82.             
  83.         DetachResource(rsrc);
  84.         AddResource(rsrc, list->realType, list->id, "\p");
  85.         
  86.         if (err = ResError())
  87.             goto finish;
  88.         
  89.         ++list;
  90.     }
  91.     
  92. finish:
  93.     UseResFile(from);
  94.     
  95.     return err;
  96. }
  97.  
  98. OSErr CopyRsrc(FSSpec * from, FSSpec * to)
  99. {
  100.     OSErr        err;
  101.     short     res;
  102.     short        fromRef;
  103.     short        toRef;
  104.     Handle    copy;
  105.     Ptr        buffer;
  106.     long        len;
  107.     
  108.     copy         = NewHandle(4096);
  109.     buffer     = *copy;
  110.     HLock(copy);
  111.     
  112.     if (err = DoOpenResFile(to, &res, true))
  113.         goto disposeBuffer;
  114.     
  115.     CloseResFile(res);
  116.     
  117.     if (err = HOpenRF(from->vRefNum, from->parID, from->name, fsRdPerm, &fromRef))
  118.         goto disposeBuffer;
  119.     if (err = HOpenRF(to->vRefNum, to->parID, to->name, fsRdWrPerm, &toRef))
  120.         goto closeFrom;
  121.  
  122.     do {
  123.         len    =    4096;
  124.         
  125.         FSRead(fromRef, &len, buffer);
  126.         FSWrite(toRef, &len, buffer);
  127.     } while (len == 4096);
  128.     
  129.     FSClose(toRef);
  130.     
  131. closeFrom:
  132.     FSClose(fromRef);
  133. disposeBuffer:
  134.     DisposeHandle(copy);
  135.     
  136.     return err;
  137. }
  138.  
  139. ShoppingList DropletShopping[] =
  140. {
  141.     { 'MrPC',    0, 'CODE' },
  142.     { 'MrPC',    1, 'CODE' },
  143.     { 'MrPC',    2, 'CODE' },
  144.     { 'MrPB',  128, 'BNDL' },
  145.     { 'MrPL',    0, 'MrPL' },
  146.     { 'MrPS',   -1, 'SIZE' },
  147.     { 'MrPI',  128, 'ICN#' },
  148.     { 'MrP4',  128, 'icl4' },
  149.     { 'MrP8',  128, 'icl8' },
  150.     { 'MrP#',  128, 'ics#' },
  151.     { 'MrPA', 4096, 'ALRT' },
  152.     { 'MrPD', 4096, 'DITL' },
  153.     { 'FREF',  128, 'FREF' },
  154.     { 'FREF',  129, 'FREF' },
  155.     { 'FREF',  131, 'FREF' },
  156.     { 'MrPF',  132, 'FREF' },
  157.     { 'MrPF',  133, 'FREF' },
  158.     { 'MrPF',  134, 'FREF' },
  159.     {          0,    0,      0 }
  160. };
  161.  
  162. OSErr MakeDroplet(FSSpec * spec, short * resFile)
  163. {
  164.     OSErr    err;
  165.     
  166.     if (err = DoOpenResFile(spec, resFile, true))
  167.         return err;
  168.     
  169.     return CopyShoppingList(gAppFile, *resFile, DropletShopping);
  170. }
  171.  
  172. OSErr Make6Runtime(FSSpec * spec, short * resFile)
  173. {
  174.     OSErr        err;
  175.     FSSpec    from;
  176.     
  177.     from.vRefNum    =    gAppVol;
  178.     from.parID        =    gAppDir;
  179.     PLstrcpy(from.name, "\pMacPerl Runtime");
  180.     
  181.     if (!CopyRsrc(&from, spec))
  182.         return DoOpenResFile(spec, resFile, false);
  183.     
  184.     err = 
  185.         FindFolder(
  186.             kOnSystemDisk, 
  187.             kPreferencesFolderType, 
  188.             true, 
  189.             &from.vRefNum,
  190.             &from.parID);
  191.     
  192.     if (err || (err = CopyRsrc(&from, spec))) {
  193.         DialogPtr    dlg;
  194.         short            item;
  195.         
  196.         ParamText(    
  197.             "\pTo create System 6 compatible Perl runtimes, I need"
  198.             "\"MacPerl Runtime\" in the same folder as this application or"
  199.             "in the preferences folder.", "\pOK", "\p", "\p");
  200.         
  201.         dlg = GetNewDialog(2001, (WindowPtr) nil, (WindowPtr) -1);
  202.         ShowWindow(dlg);
  203.         ModalDialog(nil, &item);
  204.         DisposeDialog(dlg);
  205.         
  206.         return userCanceledErr;
  207.     }
  208.         
  209.     return DoOpenResFile(spec, resFile, false);
  210. }
  211.  
  212. ShoppingList Runtime7Shopping[] =
  213. {
  214.     { 'MrPB',  128, 'BNDL' },
  215.     { 'MrPI',  128, 'ICN#' },
  216.     { 'MrP4',  128, 'icl4' },
  217.     { 'MrP8',  128, 'icl8' },
  218.     { 'MrP#',  128, 'ics#' },
  219.     { 'MrPF',  132, 'FREF' },
  220.     { 'MrPF',  133, 'FREF' },
  221.     { 'MrPF',  134, 'FREF' },
  222.     {          0,    0,      0 }
  223. };
  224.  
  225. OSErr Make7Runtime(FSSpec * spec, short * resFile)
  226. {
  227.     OSErr        err;
  228.     FSSpec    from;
  229.     
  230.     from.vRefNum    =    gAppVol;
  231.     from.parID        =    gAppDir;
  232.     PLstrcpy(from.name, (StringPtr) CurApName);
  233.  
  234.     if (err = CopyRsrc(&from, spec))
  235.         return err;
  236.         
  237.     if (err = DoOpenResFile(spec, resFile, false))
  238.         return err;
  239.         
  240.     return CopyShoppingList(gAppFile, *resFile, Runtime7Shopping);
  241. }
  242.  
  243. #ifdef RUNTIME
  244. #define HOpenDF    HOpen
  245. #endif
  246.  
  247. pascal OSErr DoSave(DPtr theDocument, FSSpec theFSSpec)
  248. {
  249.     OSErr               err;
  250.     short                resFile;
  251.     OSType            type;
  252.     Handle            text    =     (*(theDocument->theText))->hText;
  253.     Handle            thePHandle;
  254.     HHandle            theHHandle;
  255.     StringHandle    theAppName;
  256.  
  257.     HDelete(theFSSpec.vRefNum, theFSSpec.parID, theFSSpec.name);
  258.     
  259.     switch (theDocument->type) {
  260.     case kPlainTextDoc:
  261.         {
  262.             short        refNum;
  263.             long        length;
  264.             
  265.         if (err = DoOpenResFile(&theFSSpec, &resFile, false))
  266.             return err;
  267.             
  268.         if (err = 
  269.                 HOpenDF(
  270.                     theFSSpec.vRefNum, theFSSpec.parID, theFSSpec.name,
  271.                     fsRdWrPerm, &refNum)
  272.             ) {
  273.                 if (err = DoCreate(theFSSpec))
  274.                     goto closeResource;
  275.                 
  276.                 if (err =
  277.                     HOpenDF(
  278.                         theFSSpec.vRefNum, theFSSpec.parID, theFSSpec.name,
  279.                         fsRdWrPerm, &refNum)
  280.                 ) {
  281.                     FileError("\perror opening file ", theFSSpec.name);
  282.                     
  283.                     goto closeResource;
  284.                 }
  285.             }
  286.             
  287.             length     = GetHandleSize(text);
  288.             
  289.             HLock(text);
  290.             
  291.             err = FSWrite(refNum, &length, *text);
  292.             
  293.             HUnlock(text);
  294.             FSClose(refNum);
  295.             
  296.             if (err)
  297.                 goto closeResource;
  298.         }
  299.         break;
  300.     case kScriptDoc:
  301.         if (err = MakeDroplet(&theFSSpec, &resFile))
  302.             return err;
  303.         
  304.         type = 'SCPT';
  305.         
  306.         goto writeScript;
  307.     case kRuntime6Doc:
  308.         if (err = Make6Runtime(&theFSSpec, &resFile))
  309.             return err;
  310.         
  311.         type = 'MrP6';
  312.         
  313.         goto writeScript;
  314.     case kRuntime7Doc:
  315.         if (err = Make7Runtime(&theFSSpec, &resFile))
  316.             return err;
  317.         
  318.         type = 'MrP7';
  319.         
  320. writeScript:            
  321.         if (err = HandToHand(&text))
  322.             goto closeResource;
  323.         
  324.         UseResFile(resFile);
  325.         
  326.         AddResource(text, 'TEXT', 128, "\p!");
  327.         if (err = ResError()) {
  328.             DisposeHandle(text);
  329.             
  330.             goto closeResource;
  331.         }
  332.         
  333.         if (err = PtrToHand(&type, &text, 4))
  334.             goto closeResource;
  335.         
  336.         AddResource(text, 'MrPL', 128, "\p");
  337.         if (err = ResError()) {
  338.             DisposeHandle(text);
  339.             
  340.             goto closeResource;
  341.         }
  342.             
  343.         break;
  344.     }
  345.     
  346.     /* write out the printer info */
  347.     if (theDocument->thePrintSetup) {
  348.         thePHandle = (Handle)theDocument->thePrintSetup;
  349.         HandToHand(&thePHandle);
  350.  
  351.         AddResource(thePHandle, 'TFSP', 255, "\pPrinter Info");
  352.         err = ResError();
  353.         if (err = ResError()) {
  354.             ShowError("\pAddResource TFSP", err);
  355.             return err;
  356.         }
  357.     }
  358.  
  359.     theHHandle = (HHandle)NewHandle(sizeof(HeaderRec));
  360.      HLock((Handle)theHHandle);
  361.  
  362.     (*theHHandle)->theRect     = theDocument->theWindow->portRect;
  363.     OffsetRect(
  364.         &(*theHHandle)->theRect,
  365.         -theDocument->theWindow->portBits.bounds.left,
  366.         -theDocument->theWindow->portBits.bounds.top);
  367.         
  368.     GetFontName((*(theDocument->theText))->txFont, &(*theHHandle)->theFont);
  369.     
  370.     (*theHHandle)->theSize     = (*(theDocument->theText))->txSize;
  371.     (*theHHandle)->lastID      = theDocument->kind == kDocumentWindow ? theDocument->u.reg.lastID : 0;
  372.     (*theHHandle)->numSections = theDocument->kind == kDocumentWindow ? theDocument->u.reg.numSections : 0;
  373.  
  374.     HUnlock((Handle)theHHandle);
  375.  
  376.     AddResource((Handle)theHHandle, 'TFSS', 255, "\pHeader Info");
  377.     if (err = ResError()) {
  378.         ShowError("\pAddResource- TFSS", err);
  379.         return err;
  380.     }
  381.  
  382. #ifndef RUNTIME
  383.     /*if we have any sections, write out the records and resources*/
  384.  
  385.     if (theDocument->kind == kDocumentWindow && theDocument->u.reg.numSections) {
  386.         /*now write out the section records*/
  387.         SaveSections(theDocument);
  388.  
  389.         /*write the latest versions of all editions to their containers*/
  390.  
  391.         WriteAllEditions(theDocument);
  392.     }
  393. #endif
  394.  
  395.     if (theDocument->type == kPlainTextDoc) {
  396.         /*Now put an AppName in for Finder in 7.0*/
  397.     
  398.         theAppName = (StringHandle)NewHandle(8);
  399.         PLstrcpy(*theAppName,"\pMacPerl");
  400.     
  401.         AddResource((Handle)theAppName, 'STR ', - 16396, "\pFinder App Info");
  402.         if (err = ResError()) {
  403.             ShowError("\pAppName", err);
  404.             return err;
  405.         }
  406.     }
  407.     
  408.     if (theDocument->kind == kDocumentWindow) {
  409.         theDocument->dirty = false;
  410.         theDocument->u.reg.everSaved = true;
  411.     }
  412.  
  413. closeResource:
  414.     CloseResFile(resFile);
  415.     UseResFile(gAppFile);
  416.     
  417.     return err;
  418. }
  419.  
  420.